package com.gmall.order.config;

import com.gmall.order.annotation.BeforeRepeat;
import com.gmall.order.annotation.Repeat;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

@Component
@Aspect
public class RepeatAspect {

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * 拦截住所有加了BeforeRepeat注解的方法,Pointcut 方法的集合
     */
    @Pointcut(value = "@annotation(com.gmall.order.annotation.BeforeRepeat)")
    public void beforeRepeatMethodPointCut() {

    }

    @After("beforeRepeatMethodPointCut()")
    public void beforeRepeatMethod(JoinPoint point) {

        String uuid = UUID.randomUUID().toString();
        MethodSignature signature = (MethodSignature) point.getSignature();
        BeforeRepeat annotation = signature.getMethod().getAnnotation(BeforeRepeat.class);
        String value = annotation.value();
        redisTemplate.opsForValue().set(value + uuid, uuid);

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        if (attributes != null) {
            HttpServletResponse response = attributes.getResponse();
            response.addHeader("RepeatUUID_2109A", uuid);
        }
    }

    @Pointcut(value = "@annotation(com.gmall.order.annotation.Repeat)")
    public void repeatMethodPointCut() {

    }

    @Around("repeatMethodPointCut()")
    public Object repeatMethod(ProceedingJoinPoint proceedingJoinPoint) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
        if (attributes != null) {
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            Repeat annotation = signature.getMethod().getAnnotation(Repeat.class);
            String value = annotation.value();

            HttpServletRequest request = attributes.getRequest();
            String uuid = request.getHeader("RepeatUUID_2109A");
            Boolean hasKey = redisTemplate.hasKey(value + uuid);
            if (!hasKey) {
                throw new RuntimeException("请勿重复提交");
            }

            try {
                Object o = proceedingJoinPoint.proceed();//执行原来的方法
                redisTemplate.delete(value + uuid);
                return o;
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }
}
